package com.gdpu.service.impl;
import com.gdpu.api.CommonPage;
import com.gdpu.common.ApiException;
import com.gdpu.common.Asserts;
import com.gdpu.component.CancelMessageSender;
import com.gdpu.dao.PmsGoodDao;
import com.gdpu.dao.PortalOmsCartItemDao;
import com.gdpu.dao.PortalOmsOrderDao;
import com.gdpu.dao.PortalOmsOrderItemDao;
import com.gdpu.dto.OrderParam;
import com.gdpu.enumClass.OrderStatus;
import com.gdpu.enumClass.PayStatus;
import com.gdpu.mapper.OmsOrderItemMapper;
import com.gdpu.mapper.OmsOrderMapper;
import com.gdpu.mapper.UmsAddressMapper;
import com.gdpu.mapper.UmsMemberMapper;
import com.gdpu.model.*;
import com.gdpu.serivce.RedisService;
import com.gdpu.service.PortalOmsOrderService;
import com.gdpu.service.UmsMemberService;
import com.gdpu.vo.OmsCartGoodInfoVo;
import com.gdpu.vo.OmsCartItemVo;
import com.gdpu.vo.OmsOrderListVo;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author:weiming
 * @Date:2021/5/30
 */
@Service
public class PortalOmsOrderServiceImpl  implements PortalOmsOrderService {

    @Autowired
    private PortalOmsOrderDao omsOrderDao;
    @Autowired
    private PortalOmsCartItemDao omsCartItemDao;
    @Autowired
    private PortalOmsOrderItemDao omsOrderItemDao;
    @Autowired
    private UmsAddressMapper umsAddressMapper;
    @Autowired
    private  OmsOrderMapper omsOrderMapper;
    @Autowired
    private UmsMemberMapper umsMemberMapper;
    @Autowired
    private OmsOrderItemMapper omsOrderItemMapper;
    @Autowired
    private PmsGoodDao pmsGoodDao;
    @Autowired
    private UmsMemberService umsMemberService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private CancelMessageSender cancelMessageSender;

    private Logger logger = LoggerFactory.getLogger(PortalOmsOrderServiceImpl.class);


    @Override
    public CommonPage get(Integer status, Integer pageNum, Integer pageSize) {

        OmsOrderExample example = new OmsOrderExample();
        example.setOrderByClause("create_time desc");

        OmsOrderExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(umsMemberService.getCurrentMember().getId());
        if (status != null){
            criteria.andOrderStatusEqualTo(status);
        }
        Integer offset = pageSize * (pageNum-1);
        List<OmsOrderListVo> orderList = omsOrderDao.getOrderList(umsMemberService.getCurrentMember().getId(),status,offset,pageSize);
        for (OmsOrderListVo orderListVo : orderList) {
            int total = 0;
            List<OmsOrderItem> goodImgList = orderListVo.getGoodImgList();
            for (OmsOrderItem omsOrderItem : goodImgList) {
                Integer goodQuantity = omsOrderItem.getGoodQuantity();
                total += goodQuantity;
            }
            orderListVo.setQuantity(total);
        }
        Long totalRecord = omsOrderDao.queryRecordTotal(status);
        CommonPage<OmsOrderListVo> commonPage = CommonPage.restPage(orderList, pageNum, pageSize, totalRecord);
        return commonPage;
    }

    @Override
    public Map<String, Object> generateConfirmOrder(List<Integer> cartItemIds) {
        Map<String, Object> map = new HashMap(3);
        // 根据购物车id 返回 所选商品信息
        List<OmsCartItemVo> goodsList = omsOrderDao.selectByCartIds(cartItemIds);
        map.put("cartItemList", goodsList);
        // 计算订单商品总价
        BigDecimal totalPrice = calculateTotalPrice(goodsList);
        String totalPriceStr = totalPrice.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        map.put("totalPrice", totalPriceStr);
        // 获取用户地址默认地址，联系方式，收货人
        UmsAddressExample example = new UmsAddressExample();
        example.createCriteria().andUserIdEqualTo(umsMemberService.getCurrentMember().getId()).
                andIsDefaultEqualTo(1).andIsDeletedEqualTo(0);
        List<UmsAddress> umsAddresses = umsAddressMapper.selectByExample(example);
        UmsAddress umsAddress = null;
        if (!umsAddresses.isEmpty()){
            umsAddress = umsAddresses.get(0);
        }
        map.put("userAddress", umsAddress);
        return map;
    }

    @Override
    @Transactional
    public Map<String, Object> generateOrder(OrderParam orderParam) {
        Map map = new HashMap(3);
        OmsOrder omsOrder = new OmsOrder();
        String orderSn = generateOrderSn();
        // 获取下单商品
        List<Integer> cartIds = orderParam.getCartIds();
        // 根据id获取商品价格，名称，单个商品价格
        List<OmsCartItemVo> orderItemList = omsOrderDao.selectByCartIds(cartIds);

        // 设置订单信息
        omsOrder.setOrderSn(orderSn);
        omsOrder.setOrderStatus(OrderStatus.UNPAY.getStatusCode());
        omsOrder.setCreateTime(new Date());
        omsOrder.setPayType(orderParam.getPayType());
        omsOrder.setPayStatus(PayStatus.UNPAY.getStatusCode());
        // 获取订单收件人，信息地址，联系方式
        Integer addressId = orderParam.getMemberReceiveAddressId();
        UmsAddress umsAddress = umsAddressMapper.selectByPrimaryKey(addressId);
        omsOrder.setUserId(umsMemberService.getCurrentMember().getId());
        omsOrder.setUserAddress(umsAddress.getUserAddress());
        omsOrder.setUserName(umsAddress.getUserName());
        omsOrder.setUserPhone(umsAddress.getUserPhone());
        omsOrder.setOrderNote(orderParam.getNote());
        // 订单总价
        BigDecimal orderTotalPrice = calculateTotalPrice(orderItemList);
        omsOrder.setTotalPrice(orderTotalPrice);
        omsOrderMapper.insert(omsOrder);
        // 批量插入订单商品表
        insertOrderItem(orderItemList,omsOrder.getId());
        // 购物车删除商品
        cartDeleteGoods(cartIds);
        // 发送延时取消订单消息
        cancelMessageSender.sendDelayCancelMessage(omsOrder.getId());

        map.put("order", omsOrder);
        map.put("orderItemList",orderItemList);
        return map;
    }

    private void insertOrderItem(List<OmsCartItemVo> goodsList, Integer orderId) {

        List<OmsOrderItem> omsCartItemsList = new ArrayList<>();
        for (OmsCartItemVo cartItemVo : goodsList) {
            OmsOrderItem omsOrderItem = new OmsOrderItem();
            OmsCartGoodInfoVo pmsGoods = cartItemVo.getPmsGoods();
            BigDecimal goodPrice = pmsGoods.getGoodPrice();
            // 单个商品单价*数量
            BigDecimal quantity = new BigDecimal(cartItemVo.getQuantity());
            BigDecimal singleGoodTotalPrice = pmsGoods.getGoodPrice().multiply(quantity);
            omsOrderItem.setOrderId(orderId);
            omsOrderItem.setGoodId(pmsGoods.getGoodId());
            omsOrderItem.setGoodName(pmsGoods.getGoodName());
            omsOrderItem.setGoodPrice(pmsGoods.getGoodPrice());
            omsOrderItem.setTotalPrice(singleGoodTotalPrice);
            omsOrderItem.setGoodQuantity(cartItemVo.getQuantity());
            omsOrderItem.setGoodImg(pmsGoods.getMainImage());
            omsCartItemsList.add(omsOrderItem);
        }
        omsOrderItemDao.insertBatch(omsCartItemsList);
    }

    @Override
    @Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)
    public int pay(Integer orderId) {
        int count;
        OmsOrder omsOrder = omsOrderMapper.selectByPrimaryKey(orderId);
        if (omsOrder.getPayStatus().equals(PayStatus.HASPAY.getStatusCode())){
            throw new ApiException("订单已支付，请勿重复支付！");
        }
        BigDecimal totalPrice = omsOrder.getTotalPrice();
        UmsMember umsMember = umsMemberMapper.selectByPrimaryKey(umsMemberService.getCurrentMember().getId());
        BigDecimal leftAccount = umsMember.getAccount().subtract(totalPrice);
        umsMember.setAccount(leftAccount);
        // 余额判断
        if (leftAccount.compareTo(new BigDecimal(0)) >= 0){
            count = umsMemberMapper.updateByPrimaryKeySelective(umsMember);
            omsOrder.setPayStatus(PayStatus.HASPAY.getStatusCode());
            // 支付方式（余额）
            omsOrder.setPayType(0);
            omsOrder.setPayTime(new Date());
            omsOrder.setOrderStatus(OrderStatus.WAIT_DELIVER.getStatusCode());
            omsOrder.setUpdateTime(new Date());
            omsOrderMapper.updateByPrimaryKeySelective(omsOrder);
            // 获取订单商品(商品id,数量)
            List<OmsOrderItem> orderItemList = getOrderGoodItem(omsOrder.getId());
            // 减库存,加销量
            updateGoodInfo(orderItemList);
            // 销量

        }else {
            throw new ApiException("余额不足，支付失败");
        }
        return count;
    }

    /**
     * 用户取消订单
     * @param orderId
     * @return
     */
    @Override
    public int cancel(Integer orderId) {
        int count = 0;
        OmsOrder omsOrder = omsOrderMapper.selectByPrimaryKey(orderId);
        Integer userId = umsMemberService.getCurrentMember().getId();
        if (!omsOrder.getUserId().equals(userId)) {
            Asserts.fail("不能取消他人的订单");
        }
        // 发货前都可以取消
        Integer orderStatus = omsOrder.getOrderStatus();
        if (orderStatus.compareTo(OrderStatus.CANCEL.getStatusCode())==0) {
            Asserts.fail("当前订单状态是已取消");
        }
        if (orderStatus.compareTo(OrderStatus.WAIT_DELIVER.getStatusCode()) < 0){
            omsOrder.setOrderStatus(OrderStatus.CANCEL.getStatusCode());
            count = omsOrderMapper.updateByPrimaryKeySelective(omsOrder);
            // 如果已经支付了要库存回加（支付减库存）
            if (orderStatus.compareTo(OrderStatus.FINISHED.getStatusCode()) >= 0){
                stockRollBack(orderId);
            }

        }else {
            Asserts.fail("当前订单状态是已取消");
        }
        return count;
    }

    @Override
    public Map detail(Integer orderId) {
        OmsOrder omsOrder = omsOrderMapper.selectByPrimaryKey(orderId);
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(orderId);
        List<OmsOrderItem> orderItemList = omsOrderItemMapper.selectByExample(example);
        Map<String, Object> map = new HashMap<>(2);
        map.put("omsOrderDetail",omsOrder);
        map.put("orderItemList",orderItemList);
        return map;
    }

    @Override
    public void cancelTimeOutOrder(Integer orderId) {
        OmsOrder omsOrder = omsOrderMapper.selectByPrimaryKey(orderId);
        if (omsOrder.getOrderStatus().equals(OrderStatus.UNPAY.getStatusCode())){
            omsOrder.setOrderStatus(OrderStatus.CANCEL.getStatusCode());
            logger.debug("订单编号"+ omsOrder.getOrderSn()+"订单超时支付，自动取消订单");
            omsOrderMapper.updateByPrimaryKey(omsOrder);
        }else {
            return;
        }
    }

    @Override
    public int confirmGet(Integer orderId) {
        OmsOrder record = new OmsOrder();
        record.setId(orderId);
        record.setOrderStatus(OrderStatus.FINISHED.getStatusCode());
        int count = omsOrderMapper.updateByPrimaryKeySelective(record);
        return count;
    }

    /**
     * 库存回加
     * @param orderId
     */
    private void stockRollBack(Integer orderId) {
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(orderId);
        List<OmsOrderItem> orderItemList = omsOrderItemMapper.selectByExample(example);
    }

    /**
     * 扣减商品库存
     * @param orderItemList
     */
    private void updateGoodInfo(List<OmsOrderItem> orderItemList) {
        pmsGoodDao.updateGoodInfoBatch(orderItemList);
    }

    /**
     * 根据订单id获取订单商品
     * @param orderId
     * @return
     */
    private List<OmsOrderItem> getOrderGoodItem(Integer orderId) {
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(orderId);
        List<OmsOrderItem> orderItemList = omsOrderItemMapper.selectByExample(example);
        return orderItemList;
    }

    /**
     *
     * @param cardIds
     */
    private void cartDeleteGoods(List<Integer> cardIds) {

        Integer count = omsCartItemDao.deleteByIds(cardIds);


    }

    private String generateOrderSn() {
        StringBuilder stringBuilder = new StringBuilder();
        String prefix = "DD";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateString = sdf.format(new Date());
        Date date = new Date();
        //TODO 自增redisId
        redisService.incr("oms_order_id:"+dateString, 1);
        redisService.expire("oms_order_id:"+dateString,3600*24);
        Integer oms_order_id = (Integer) redisService.get("oms_order_id:"+dateString);
        stringBuilder.append(prefix)
                .append(dateString)
                .append(String.format("%03d", oms_order_id));
        return stringBuilder.toString();
    }

    /**
     * 计算订单商品总价
     * @param cartItemVos
     * @return
     */
    private BigDecimal calculateTotalPrice(List<OmsCartItemVo> cartItemVos){
        BigDecimal totalPrice = new BigDecimal(0);
        for (OmsCartItemVo cartItem : cartItemVos){
            OmsCartGoodInfoVo pmsGoods = cartItem.getPmsGoods();
            BigDecimal goodPrice = pmsGoods.getGoodPrice();
            Integer quantity = cartItem.getQuantity();
            // 单个商品 * 数量
            BigDecimal goodTotalPrice = goodPrice.multiply(new BigDecimal(quantity));
            totalPrice = totalPrice.add(goodTotalPrice);
        }
        return totalPrice;
    }




}
